using System.Collections;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;

namespace KinonekoSoftware.Studio.Collections
{
    public sealed class DictionaryCollection<TKey, TValue> : Collection<TValue>
    {
        private readonly Dictionary<TKey, TValue> _dictionary;
        private readonly List<TValue>             _collection;
        private readonly Func<TValue, TKey>       _selector;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="selector"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public DictionaryCollection(Func<TValue, TKey> selector) : this(16, selector)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="capacity"></param>
        /// <param name="selector"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public DictionaryCollection(int capacity, Func<TValue, TKey> selector): base(new List<TValue>(Math.Min(16, capacity)))
        {
            _selector   = selector ?? throw new ArgumentNullException(nameof(selector));
            _collection = (List<TValue>)Items;
            _dictionary = new Dictionary<TKey, TValue>();
        }

        protected override void ClearItems()
        {
            _dictionary.Clear();
            _collection.Clear();
            base.ClearItems();
        }

        protected override void InsertItem(int index, TValue item)
        {
            //
            //
            _dictionary.TryAdd(_selector(item), item);
            _collection.Insert(index, item);
        }

        protected override void SetItem(int index, TValue item)
        {
            var old = _collection[index];

            //
            //
            _dictionary.TryAdd(_selector(item), item);
            _dictionary.Remove(_selector(old));
            _collection[index] = item;
        }

        protected override void RemoveItem(int index)
        {
            var item = _collection[index];

            //
            //
            _dictionary.Remove(_selector(item));
            _collection.Remove((item));

            //
            //
            base.RemoveItem(index);
        }

        public List<TValue>             Collection => _collection;
        public Dictionary<TKey, TValue> Dictionary => _dictionary;
    }
}